package asruby
{
import asruby.exceptions.RaiseException;
import asruby.exceptions.RubyLocalJumpError;
import asruby.lang.Profile;
import asruby.lang.RubyArray;
import asruby.lang.RubyBoolean;
import asruby.lang.RubyClass;
import asruby.lang.RubyComparable;
import asruby.lang.RubyEnumerable;
import asruby.lang.RubyException;
import asruby.lang.RubyFixnum;
import asruby.lang.RubyFloat;
import asruby.lang.RubyHash;
import asruby.lang.RubyInteger;
import asruby.lang.RubyModule;
import asruby.lang.RubyNil;
import asruby.lang.RubyNumeric;
import asruby.lang.RubyObject;
import asruby.lang.RubyString;
import asruby.lang.RubySymbol;
import asruby.lang.RubyUndef;
import asruby.lang.RubyWarnings;
import asruby.runtime.CacheMap;
import asruby.runtime.CallbackFactory;
import asruby.runtime.GlobalVariable;
import asruby.runtime.GlobalVariables;
import asruby.runtime.IRubyObject;
import asruby.runtime.ObjectSpace;
import asruby.runtime.ThreadContext;
import asruby.runtime.load.LoadService;
import asruby.util.JRubyClassLoader;
import asruby.yarv.YARVRunner;

import flash.display.Sprite;
import flash.utils.Dictionary;	
public class Ruby
{
    // Default objects
    public var undef: IRubyObject;
    public var topSelf: IRubyObject;
    public var nilObject: RubyNil;
    public var trueObject: RubyBoolean;
    public var falseObject: RubyBoolean;
    public var fixnumCache: Array = new Array();
	private  var cacheMap: CacheMap =  new CacheMap();
	private  var globalState: Number =  1;
    private  var _threadContext:ThreadContext;
    private  var _hasEventHooks:Boolean;  
    private  var symbolTable: Dictionary =  new Dictionary;
    public var verbose: IRubyObject;
    public var debug: IRubyObject;
    private  var safeLevel: int =  -1;
    private  var stackTraces: int =  0;
	private var loadService: LoadService;
    private var globalVariables: GlobalVariables;
    private var warnings: RubyWarnings;
    private var objectSpace:ObjectSpace;
    
 	private var profile: Profile;
 	
    // Contains a list of all blocks (as Procs) that should be called when
    // the runtime environment exits.
    private var atExitBlocks: Array = new Array();

   /*  private var kcode: KCode = KCode.NONE; */

    // Atomic integers for symbol and method IDs
    private var symbolLastId: Number = new Number(128);
    private var moduleLastId: Number = new Number(0);

    private var respondToMethod: Object;
    private var objectToYamlMethod: Object;

  	private var objectClass, moduleClass, classClass, nilClass, trueClass,
            falseClass, numericClass, floatClass, integerClass, fixnumClass,
            arrayClass, hashClass, rangeClass, stringClass, symbolClass,
            procClass, bindingClass, methodClass, unboundMethodClass,
            matchDataClass, regexpClass, timeClass: RubyClass
            ,enumerableModule:RubyModule;
    /**
     * Returns a new instance of the JRuby runtime configured as specified.
     *
     * @param config The instance configuration
     * @return The JRuby runtime
     * @see org.jruby.RubyInstanceConfig
     */
    public static function  newInstance(stage:Sprite): Ruby {
        var ruby: Ruby = new Ruby();
        //ruby.init(stage);
        return ruby;
    }
    
    /**
     * Create and initialize a new JRuby runtime. The properties of the
     * specified RubyInstanceConfig will be used to determine various JRuby
     * runtime characteristics.
     * 
     * @param config The configuration to use for the new instance
     * @see org.jruby.RubyInstanceConfig
     */
    public function  Ruby() {
/*         var this.in:                  = config.getInput();
        var this.out:                 = config.getOutput();
        var this.err:                 = config.getError();
        var this.objectSpaceEnabled:  = config.isObjectSpaceEnabled();
        var this.profile:             = config.getProfile();
        var this.currentDirectory:    = config.getCurrentDirectory();
        var this.kcode:               = config.getKCode(); */
    }
    
 	private function  bootstrap(): void {
        undef = new RubyUndef();        
        initRoot();
        initCore();
        initExceptions();
    }

    private function  initRoot(): void {
        // Bootstrap the top of the hierarchy
        objectClass = RubyClass.createBootstrapClass(this, "Object", null, RubyObject.OBJECT_ALLOCATOR);
        moduleClass = RubyClass.createBootstrapClass(this, "Module", objectClass, RubyModule.MODULE_ALLOCATOR);
        classClass = RubyClass.createBootstrapClass(this, "Class", moduleClass, RubyClass.CLASS_ALLOCATOR);

        objectClass.setMetaClass(classClass);
        moduleClass.setMetaClass(classClass);
        classClass.setMetaClass(classClass);

        var metaClass:RubyClass;
        metaClass = objectClass.makeMetaClass(classClass);
        metaClass = moduleClass.makeMetaClass(metaClass);
        metaClass = classClass.makeMetaClass(metaClass);

        RubyObject.createObjectClass(this, objectClass);
        RubyModule.createModuleClass(this, moduleClass);
        RubyClass.createClassClass(this, classClass);
        
        // set constants now that they're initialized
        objectClass.setConstant("Object", objectClass);
        objectClass.setConstant("Class", classClass);
        objectClass.setConstant("Module", moduleClass);

        // Initialize Kernel and include into Object
/*         RubyKernel.createKernelModule(this);
        objectClass.includeModule(kernelModule);
 */
        // Object is ready, create top self
        //topSelf = TopSelfFactory.createTopSelf(this);
    }
    
  	private function  initCore(): void {
  		globalVariables = new GlobalVariables(this);
  		warnings = new RubyWarnings(this);
        // Pre-create all the core classes potentially referenced during startup
        RubyNil.createNilClass(this);
        RubyBoolean.createFalseClass(this);
        RubyBoolean.createTrueClass(this);

        nilObject = new RubyNil(this);
        falseObject = new RubyBoolean(this, false);
        trueObject = new RubyBoolean(this, true);

        RubyComparable.createComparable(this);
        RubyEnumerable.createEnumerableModule(this);
        RubyString.createStringClass(this);
        RubySymbol.createSymbolClass(this);

        if (profile.allowClass("Exception")) {
            RubyException.createExceptionClass(this);
        }
		/* if (profile.allowModule("Precision")) {
            RubyPrecision.createPrecisionModule(this);
        } */
        if (profile.allowClass("Numeric")) {
            RubyNumeric.createNumericClass(this);
        }
        if (profile.allowClass("Integer")) {
            RubyInteger.createIntegerClass(this);
        }
        if (profile.allowClass("Fixnum")) {
            RubyFixnum.createFixnumClass(this);
        }
        if (profile.allowClass("Hash")) {
            RubyHash.createHashClass(this);
        }
        if (profile.allowClass("Array")) {
            RubyArray.createArrayClass(this);
        }
        if (profile.allowClass("Float")) {
            RubyFloat.createFloatClass(this);
        }
/*
        if (profile.allowClass("Bignum")) {
            RubyBignum.createBignumClass(this);
        }
        ioClass = RubyIO.createIOClass(this);

        if (profile.allowClass("Struct")) {
            RubyStruct.createStructClass(this);
        }
        
        if (profile.allowClass("Tms")) {
            tmsStruct = RubyStruct.newInstance(structClass, 
            	[newString("Tms"), newSymbol("utime"), newSymbol("stime"), newSymbol("cutime"), newSymbol("cstime")], Block.NULL_BLOCK);
        } 

        if (profile.allowClass("Binding")) {
            RubyBinding.createBindingClass(this);
        }
        // Math depends on all numeric types
        if (profile.allowModule("Math")) {
            RubyMath.createMathModule(this);
        }
        if (profile.allowClass("Regexp")) {
            RubyRegexp.createRegexpClass(this);
        }
        if (profile.allowClass("Range")) {
            RubyRange.createRangeClass(this);
        }
        if (profile.allowModule("ObjectSpace")) {
            RubyObjectSpace.createObjectSpaceModule(this);
        }
        if (profile.allowModule("GC")) {
            RubyGC.createGCModule(this);
        }
        if (profile.allowClass("Proc")) {
            RubyProc.createProcClass(this);
        }
        if (profile.allowClass("Method")) {
            RubyMethod.createMethodClass(this);
        }
        if (profile.allowClass("MatchData")) {
            RubyMatchData.createMatchDataClass(this);
        }
        if (profile.allowModule("Marshal")) {
            RubyMarshal.createMarshalModule(this);
        }
        if (profile.allowClass("Dir")) {
            RubyDir.createDirClass(this);
        }
        if (profile.allowModule("FileTest")) {
            RubyFileTest.createFileTestModule(this);
        }
        // depends on IO, FileTest
        if (profile.allowClass("File")) {
            RubyFile.createFileClass(this);
        }
        if (profile.allowClass("File::Stat")) {
            RubyFileStat.createFileStatClass(this);
        }
        if (profile.allowModule("Process")) {
            RubyProcess.createProcessModule(this);
        }
        if (profile.allowClass("Time")) {
            RubyTime.createTimeClass(this);
        }
        if (profile.allowClass("UnboundMethod")) {
            RubyUnboundMethod.defineUnboundMethodClass(this);
        }
        if (profile.allowClass("Data")) {
            defineClass("Data", objectClass, objectClass.getAllocator());
        }
        if (!isSecurityRestricted()) {
            // Signal uses sun.misc.* classes, this is not allowed
            // in the security-sensitive environments
            if (profile.allowModule("Signal")) {
                RubySignal.createSignal(this);
            }
        }
        if (profile.allowClass("Continuation")) {
            RubyContinuation.createContinuation(this);
        } */
    }

    private function  initExceptions(): void {
    	
    	/*
        standardError = defineClassIfAllowed("StandardError", exceptionClass);
        runtimeError = defineClassIfAllowed("RuntimeError", standardError);
        ioError = defineClassIfAllowed("IOError", standardError);
        scriptError = defineClassIfAllowed("ScriptError", exceptionClass);
        rangeError = defineClassIfAllowed("RangeError", standardError);
        signalException = defineClassIfAllowed("SignalException", exceptionClass);
        
        if (profile.allowClass("NameError")) {
            nameError = RubyNameError.createNameErrorClass(this, standardError);
        }
        if (profile.allowClass("NoMethodError")) {
            RubyNoMethodError.createNoMethodErrorClass(this, nameError);
        }
        if (profile.allowClass("SystemExit")) {
            RubySystemExit.createSystemExitClass(this, exceptionClass);
        }
        if (profile.allowClass("LocalJumpError")) {
            RubyLocalJumpError.createLocalJumpErrorClass(this, standardError);
        }
        if (profile.allowClass("NativeException")) {
            NativeException.createClass(this, runtimeError);
        }
        if (profile.allowClass("SystemCallError")) {
            systemCallError = RubySystemCallError.createSystemCallErrorClass(this, standardError);
        }
        
        defineClassIfAllowed("Fatal", exceptionClass);
        defineClassIfAllowed("Interrupt", signalException);
        defineClassIfAllowed("TypeError", standardError);
        defineClassIfAllowed("ArgumentError", standardError);
        defineClassIfAllowed("IndexError", standardError);
        defineClassIfAllowed("SyntaxError", scriptError);
        defineClassIfAllowed("LoadError", scriptError);
        defineClassIfAllowed("NotImplementedError", scriptError);
        defineClassIfAllowed("SecurityError", standardError);
        defineClassIfAllowed("NoMemoryError", exceptionClass);
        defineClassIfAllowed("RegexpError", standardError);
        defineClassIfAllowed("EOFError", ioError);
        defineClassIfAllowed("ThreadError", standardError);
        defineClassIfAllowed("SystemStackError", standardError);
        defineClassIfAllowed("ZeroDivisionError", standardError);
        defineClassIfAllowed("FloatDomainError", rangeError);
        
        initErrno();
        */
    }
    
/* 	private function  defineClassIfAllowed(name: String, superClass: RubyClass): RubyClass {
	// TODO: should probably apply the null object pattern for a
	// non-allowed class, rather than null
        if (superClass != null && profile.allowClass(name)) {
            return defineClass(name, superClass, superClass.getAllocator());
        }
        return null;
    } */ 
    	
 	public function  runYarv(runner: YARVRunner): IRubyObject {
        try {
            return runner.run();
        } catch (rj:Error) {
            return rj.getValue();
        }
        return null;
    }
    
 	public function loadYarvOpCode(url:String): YARVRunner {
        try {
            // load op code
            //return new YARVRunner(this,compiler.getInstructionSequence("<main>",p.getFile(),"toplevel"));
        } catch (err:Error) {
            trace("Error -- Not compileable: " + err.message);
            
        }
        return null;
    }
    

 	public function  fastNewSymbol(internedName: String): RubySymbol {
        //assert internedName == internedName.intern() : internedName + " is not interned";
        return symbolTable.fastGetSymbol(internedName);
    }
    
	public function  getGlobalState(): Number {
		return globalState;
    }

 	public function  newTypeError(message: String): Error {
        return new Error(message);
    }

    public function  newFixnum(value: Number): RubyFixnum {
        return RubyFixnum.newFixnum(this, value);
    }

    public function  newFloat(value: Number): RubyFloat {
        return RubyFloat.newFloat(this, value);
    }

    public function  newNumeric(): RubyNumeric {
        return RubyNumeric.newNumeric(this);
    }

/*     public function  newProc(type: Block.Type, block: Block): RubyProc {
        if (type != Block.Type.LAMBDA && block.getProcObject() != null) return block.getProcObject();

        var proc: RubyProc =  RubyProc.newProc(this, type);

        proc.callInit(IRubyObject.NULL_ARRAY, block);

        return proc;
    } 

    public function  newBinding(): RubyBinding {
        return RubyBinding.newBinding(this);
    }
*/
    /**
     * Retrieve the module with the given name from the Object namespace.
     * 
     * @param name The name of the module
     * @return The module or null if not found
     */
    public function  getModule(name: String=null): RubyModule {
        return RubyModule(objectClass.getConstantAt(name));
    }

    /**
     * Retrieve the module with the given name from the Object namespace. The
     * module name must be an interned string, but this method will be faster
     * than the non-interned version.
     * 
     * @param internedName The name of the module; <em>must</em> be an interned String
     * @return The module or null if not found
     */
    public function  fastGetModule(internedName: String): RubyModule {
        return RubyModule(objectClass.fastGetConstantAt(internedName));
    }

    /** 
     * Retrieve the class with the given name from the Object namespace.
     *
     * @param name The name of the class
     * @return The class
     */
    public function  getClass(name: String): RubyClass {
        return objectClass.getClass(name);
    }

    /**
     * Retrieve the class with the given name from the Object namespace. The
     * module name must be an interned string, but this method will be faster
     * than the non-interned version.
     * 
     * @param internedName the name of the class; <em>must</em> be an interned String!
     * @return
     */
    public function  fastGetClass(internedName: String): RubyClass {
        return objectClass.fastGetClass(internedName);
    }

    /** 
     * Define a new class under the Object namespace. Roughly equivalent to
     * rb_define_class in MRI.
     *
     * @param name The name for the new class
     * @param superClass The super class for the new class
     * @param allocator An ObjectAllocator instance that can construct
     * instances of the new class.
     * @return The new class
     */
    public function  defineClass(name: String, superClass: RubyClass, allocator: Function): RubyClass {
        return defineClassUnder(name, superClass, allocator, objectClass);
    }

    /**
     * Define a new class with the given name under the given module or class
     * namespace. Roughly equivalent to rb_define_class_under in MRI.
     * 
     * If the name specified is already bound, its value will be returned if:
     * * It is a class
     * * No new superclass is being defined
     *
     * @param name The name for the new class
     * @param superClass The super class for the new class
     * @param allocator An ObjectAllocator instance that can construct
     * instances of the new class.
     * @param parent The namespace under which to define the new class
     * @return The new class
     */
    public function  defineClassUnder(name: String, superClass: RubyClass, allocator: Function, parent: RubyModule): RubyClass {
        var classObj: IRubyObject = parent.getConstantAt(name);

        if (classObj != null) {
            if (!(classObj instanceof RubyClass)) throw newTypeError(name + " is not a class");
            var klazz:RubyClass = RubyClass(classObj);
            if (klazz.getSuperClass().getRealClass() != superClass) {
                throw new Error(name + " is already defined", name);
            }
            // If we define a class in Ruby, but later want to allow it to be defined in Java,
            // the allocator needs to be updated
            if (klazz.getAllocator() != allocator) {
                klazz.setAllocator(allocator);
            }
            return klazz;
        }
        
        var parentIsObject: Boolean = parent == objectClass;

        if (superClass == null) {
            var className: String = parentIsObject ? name : parent.getName() + "::" + name;
            warnings.warn(RubyWarnings.NO_SUPER_CLASS, "no super class for `" + className + "', Object assumed", className);
            
            superClass = objectClass;
        }

        return RubyClass.newClass2(this, superClass, name, allocator, parent, !parentIsObject);
    }

    /** 
     * Define a new module under the Object namespace. Roughly equivalent to
     * rb_define_module in MRI.
     * 
     * @param name The name of the new module
     * @returns The new module
     */
    public function  defineModule(name: String): RubyModule {
        return defineModuleUnder(name, objectClass);
    }

    /**
     * Define a new module with the given name under the given module or
     * class namespace. Roughly equivalent to rb_define_module_under in MRI.
     * 
     * @param name The name of the new module
     * @param parent The class or module namespace under which to define the
     * module
     * @returns The new module
     */
    public function  defineModuleUnder(name: String, parent: RubyModule): RubyModule {
        var moduleObj: IRubyObject = parent.getConstantAt(name);
        
        var parentIsObject: Boolean = parent == objectClass;

        if (moduleObj != null ) {
            if (moduleObj.isModule()) return RubyModule(moduleObj);
            
            if (parentIsObject) {
                throw newTypeError(moduleObj.getMetaClass().getName() + " is not a module");
            } else {
                throw newTypeError(parent.getName() + "::" + moduleObj.getMetaClass().getName() + " is not a module");
            }
        }

        return RubyModule.newModule2(this, name, parent, !parentIsObject);
    }

    /**
     * From Object, retrieve the named module. If it doesn't exist a
     * new module is created.
     * 
     * @param name The name of the module
     * @returns The existing or new module
     */
    public function  getOrCreateModule(name: String): RubyModule {
        var module: IRubyObject = objectClass.getConstantAt(name);
        if (module == null) {
            module = defineModule(name);
        } else if (getSafeLevel() >= 4) {
            throw newSecurityError("Extending module prohibited.");
        } else if (!module.isModule()) {
            throw newTypeError(name + " is not a Module");
        }

        return RubyModule(module);
    }


    /** 
     * Retrieve the current safe level.
     * 
     * @see org.jruby.Ruby#setSaveLevel
     */
    public function  getSafeLevel(): int {
        return this.safeLevel;
    }


    /** 
     * Set the current safe level:
     * 
     * 0 - strings from streams/environment/ARGV are tainted (default)
     * 1 - no dangerous operation by tainted value
     * 2 - process/file operations prohibited
     * 3 - all generated objects are tainted
     * 4 - no global (non-tainted) variable modification/no direct output
     * 
     * The safe level is set using $SAFE in Ruby code. It is not particularly
     * well supported in JRuby.
    */
    public function  setSafeLevel(safeLevel: int): void {
        this.safeLevel = safeLevel;
    }

  	public function getRespondToMethod():Object {
        return respondToMethod;
    }

    public function setRespondToMethod( rtm:Object ):void  {
        this.respondToMethod = rtm;
    }

    /**
     * Retrieve mappings of cached methods to where they have been cached.  When a cached
     * method needs to be invalidated this map can be used to remove all places it has been
     * cached.
     *
     * @return the mappings of where cached methods have been stored
     */
/*     public function  getCacheMap(): CacheMap {
        return cacheMap;
    } */

    /** Getter for property rubyTopSelf.
     * @return Value of property rubyTopSelf.
     */
    public function  getTopSelf(): IRubyObject {
        return topSelf;
    }
    
    public function  getUndef(): IRubyObject {
        return undef;
    }
    
/*     public function  getEtc(): RubyModule {
        return etcModule;
    }
    
    public function  setEtc(etcModule: RubyModule): void {
       	this.etcModule = etcModule;
    }
 */
    public function  getObject(): RubyClass {
        return objectClass;
    }

    public function  getModule0(): RubyClass {
        return moduleClass;
    }

    public function  getClassClass(): RubyClass {
        return classClass;
    }
    
/*     public function  getKernel(): RubyModule {
        return kernelModule;
    }
    
    public function setKernel( kernelModule:RubyModule ):void {
        this.kernelModule = kernelModule;
    }    
 
    public function  getComparable(): RubyModule {
        return comparableModule;
    }
    
    public function setComparable( comparableModule:RubyModule):void {
        this.comparableModule = comparableModule;
    }    
*/
    public function  getNumeric(): RubyClass {
        return numericClass;
    }
    public function setNumeric( numericClass:RubyClass):void {
        this.numericClass = numericClass;
    }    

    public function  getFloat(): RubyClass {
        return floatClass;
    }
    public function setFloat( floatClass:RubyClass):void {
        this.floatClass = floatClass;
    }
    
    public function  getInteger(): RubyClass {
        return integerClass;
    }
    public function setInteger( integerClass:RubyClass):void {
        this.integerClass = integerClass;
    }    
    
    public function  getFixnum(): RubyClass {
        return fixnumClass;
    }
    public function setFixnum( fixnumClass:RubyClass):void {
        this.fixnumClass = fixnumClass;
    }    

    public function  getEnumerable(): RubyModule {
        return null;
    }
    public function setEnumerable( enumerableModule:RubyModule):void {
        //this.enumerableModule = enumerableModule;
    }      

    public function  getString(): RubyClass {
        return stringClass;
    }    
    public function setString( stringClass:RubyClass):void {
        this.stringClass = stringClass;
    }    

    public function  getSymbol(): RubyClass {
        return symbolClass;
    }
    public function setSymbol( symbolClass:RubyClass):void {
        this.symbolClass = symbolClass;
    }   

    public function  getArray(): RubyClass {
        return arrayClass;
    }    
    public function setArray( arrayClass:RubyClass):void {
        this.arrayClass = arrayClass;
    }

    public function  getHash(): RubyClass {
        return hashClass;
    }
    public function setHash( hashClass:RubyClass):void {
        this.hashClass = hashClass;
    }

    public function  getRange(): RubyClass {
        return rangeClass;
    }
    public function setRange( rangeClass:RubyClass):void {
        this.rangeClass = rangeClass;
    }

    /** Returns the "true" instance from the instance pool.
     * @return The "true" instance.
     */
    public function  getTrue(): RubyBoolean {
        return trueObject;
    }

    /** Returns the "false" instance from the instance pool.
     * @return The "false" instance.
     */
    public function  getFalse(): RubyBoolean {
        return falseObject;
    }

    /** Returns the "nil" singleton instance.
     * @return "nil"
     */
    public function  getNil(): IRubyObject {
        return nilObject;
    }

    public function  getNilClass(): RubyClass {
        return nilClass;
    }
    public function setNilClass( nilClass:RubyClass):void {
        this.nilClass = nilClass;
    }

    public function  getTrueClass(): RubyClass {
        return trueClass;
    }
    public function setTrueClass( trueClass:RubyClass):void {
        this.trueClass = trueClass;
    }

    public function  getFalseClass(): RubyClass {
        return falseClass;
    }
    public function setFalseClass( falseClass:RubyClass):void {
        this.falseClass = falseClass;
    }

    public function  getProc(): RubyClass {
        return procClass;
    }
    public function setProc( procClass:RubyClass):void {
        this.procClass = procClass;
    }

    public function  getBinding(): RubyClass {
        return bindingClass;
    }
    public function setBinding( bindingClass:RubyClass):void {
        this.bindingClass = bindingClass;
    }

    public function  getMethod(): RubyClass {
        return methodClass;
    }
    public function setMethod( methodClass:RubyClass):void {
        this.methodClass = methodClass;
    }    

    public function  getUnboundMethod(): RubyClass {
        return unboundMethodClass;
    }
    public function setUnboundMethod( unboundMethodClass:RubyClass):void {
        this.unboundMethodClass = unboundMethodClass;
    }    

    public function  getMatchData(): RubyClass {
        return matchDataClass;
    }
    public function setMatchData( matchDataClass:RubyClass):void {
        this.matchDataClass = matchDataClass;
    }    

    public function  getRegexp(): RubyClass {
        return regexpClass;
    }
    public function setRegexp( regexpClass:RubyClass):void {
        this.regexpClass = regexpClass;
    }    

    public function  getTime(): RubyClass {
        return timeClass;
    }
    public function setTime( timeClass:RubyClass):void {
        this.timeClass = timeClass;
    }    
/*
    public function  getMath(): RubyModule {
        return mathModule;
    }
    public function setMath( mathModule:RubyModule):void {
        this.mathModule = mathModule;
    }    

    public function  getMarshal(): RubyModule {
        return marshalModule;
    }
    public function setMarshal( marshalModule:RubyModule):void {
        this.marshalModule = marshalModule;
    }    

    public function  getBignum(): RubyClass {
        return bignumClass;
    }
    public function setBignum( bignumClass:RubyClass):void {
        this.bignumClass = bignumClass;
    }    

    public function  getDir(): RubyClass {
        return dirClass;
    }
    public function setDir( dirClass:RubyClass) {
        this.dirClass = dirClass;
    }    

    public function  getFile(): RubyClass {
        return fileClass;
    }
    public function setFile( fileClass:RubyClass):void {
        this.fileClass = fileClass;
    }    

    public function  getFileStat(): RubyClass {
        return fileStatClass;
    }
    public function setFileStat( fileStatClass:RubyClass):void {
        this.fileStatClass = fileStatClass;
    }    

    public function  getFileTest(): RubyModule {
        return fileTestModule;
    }
    public function setFileTest( fileTestModule:RubyModule):void {
        this.fileTestModule = fileTestModule;
    }
    
    public function  getIO(): RubyClass {
        return ioClass;
    }
    public function setIO( ioClass:RubyClass) {
        this.ioClass = ioClass;
    }    

    public function  getThread(): RubyClass {
        return threadClass;
    }
    public function setThread( threadClass:RubyClass):void {
        this.threadClass = threadClass;
    }    

    public function  getThreadGroup(): RubyClass {
        return threadGroupClass;
    }
    public function setThreadGroup( threadGroupClass:RubyClass):void {
        this.threadGroupClass = threadGroupClass;
    }    

    public function  getContinuation(): RubyClass {
        return continuationClass;
    }
    public function setContinuation( continuationClass:RubyClass):void {
        this.continuationClass = continuationClass;
    }    

    public function  getStructClass(): RubyClass {
        return structClass;
    }
    public function setStructClass( structClass:RubyClass):void {
        this.structClass = structClass;
    }    

    public function  getTmsStruct(): IRubyObject {
        return tmsStruct;
    }
    public function setTmsStruct( tmsStruct:RubyClass):void {
        this.tmsStruct = tmsStruct;
    }
    
    public function  getPasswdStruct(): IRubyObject {
        return passwdStruct;
    }
    public function setPasswdStruct( passwdStruct:RubyClass):void {
        this.passwdStruct = passwdStruct;
    }

    public function  getGroupStruct(): IRubyObject {
        return groupStruct;
    }
    public function setGroupStruct( groupStruct:RubyClass):void {
        this.groupStruct = groupStruct;
    }

    public function  getGC(): RubyModule {
        return gcModule;
    }
    public function setGC( gcModule:RubyModule):void {
        this.gcModule = gcModule;
    }    

    public function  getObjectSpaceModule(): RubyModule {
        return objectSpaceModule;
    }
    public function setObjectSpaceModule( objectSpaceModule:RubyModule):void {
        this.objectSpaceModule = objectSpaceModule;
    }    

    public function  getProcess(): RubyModule {
        return processModule;
    }
    public function setProcess( processModule:RubyModule):void {
        this.processModule = processModule;
    }    

    public function  getProcStatus(): RubyClass {
        return procStatusClass; 
    }
    public function setProcStatus( procStatusClass:RubyClass):void {
        this.procStatusClass = procStatusClass;
    }
    
    public function  getProcUID(): RubyModule {
        return procUIDModule;
    }
    public function setProcUID( procUIDModule:RubyModule):void {
        this.procUIDModule = procUIDModule;
    }
    
    public function  getProcGID(): RubyModule {
        return procGIDModule;
    }
    public function setProcGID( procGIDModule:RubyModule):void {
        this.procGIDModule = procGIDModule;
    }
    
    public function  getProcSysModule(): RubyModule {
        return procSysModule;
    }
    public function setProcSys( procSysModule:RubyModule):void {
        this.procSysModule = procSysModule;
    }

    public function  getPrecision(): RubyModule {
        return precisionModule;
    }
    public function setPrecision( precisionModule:RubyModule):void {
        this.precisionModule = precisionModule;
    }    

    public function  getException(): RubyClass {
        return exceptionClass;
    }
    public function setException( exceptionClass:RubyClass):void {
        this.exceptionClass = exceptionClass;
    }
    
    public function  getStandardError(): RubyClass {
        return standardError;
    }
*/
    /** Getter for property isVerbose.
     * @return Value of property isVerbose.
     */
    public function  getVerbose(): IRubyObject {
        return verbose;
    }

    /** Setter for property isVerbose.
     * @param verbose New value of property isVerbose.
     */
    public function  setVerbose(verbose: IRubyObject): void {
        this.verbose = verbose;
    }

    /** Getter for property isDebug.
     * @return Value of property isDebug.
     */
    public function  getDebug(): IRubyObject {
        return debug;
    }

    /** Setter for property isDebug.
     * @param debug New value of property isDebug.
     */
    public function  setDebug(debug: IRubyObject): void {
        this.debug = debug;
    }

/*     public function  getJavaSupport(): JavaSupport {
        return javaSupport;
    } 

    public function  getJRubyClassLoader(): JRubyClassLoader {
        // FIXME: Get rid of laziness and handle restricted access elsewhere
        if (!Ruby.isSecurityRestricted() && jrubyClassLoader == null) {
            var jrubyClassLoader = new JRubyClassLoader(config.getLoader());
        }
        
        return jrubyClassLoader;
    }
*/
	public function getJRubyClassLoader():JRubyClassLoader {
		return new JRubyClassLoader(null);
	}
    /** Defines a global variable
     */
    public function  defineVariable(variable:GlobalVariable): void {
        globalVariables.define(variable.getName(), variable.getVal() );
/*          new IAccessor(
            function  getValue(): IRubyObject {
                return variable.get();
            }
			,
            function  setValue(newValue: IRubyObject): IRubyObject {
                return variable.set(newValue);
            }
        )); */
    }

    /** defines a readonly global variable
     *
     */
    public function  defineReadonlyVariable(name: String, value: IRubyObject): void {
        globalVariables.defineReadonly(name, value);
    }

  	public function callbackFactory(type:Class):CallbackFactory {
        return CallbackFactory.createFactory(this, type);
    }
    
        
    public  function newArgumentError(message:String):Error{
        return new Error("ArgumentError", message);
    }
    public  function newNameError(message:String, name:String):Error{
        return new Error("NameError in " + name, message);
    }
    
	public  function getCurrentContext():ThreadContext{
        return _threadContext;
    } 

 	/**
     * Retrieve mappings of cached methods to where they have been cached.  When a cached
     * method needs to be invalidated this map can be used to remove all places it has been
     * cached.
     *
     * @return the mappings of where cached methods have been stored
     */
    public  function getCacheMap():CacheMap{
        return cacheMap;
    }
    
  	public  function getLoadService():LoadService {
        return loadService;
    }

/*   	public  function getObjectSpace():ObjectSpace {
        return objectSpace;
    } */

    public  function getWarnings():RubyWarnings{
        return warnings;
    }
 	
 	public  function newString(string:String):RubyString{
        return RubyString.newString(this, string);
    }

  	public  function newArray():RubyArray{
        return RubyArray.newArray(this, 0);
    } 
	public  function newArray2(object:IRubyObject):RubyArray{
        return RubyArray.newArray2(this, object);
    }
    public  function newArray3(size:int):RubyArray{
        return RubyArray.newArray(this, size);
    }
	public  function newArray4(car:IRubyObject, cdr:IRubyObject):RubyArray{
        return RubyArray.newArray3(this, car, cdr);
    }    
 	public  function getGlobalVariables():GlobalVariables{
        return globalVariables;
    }    

 	public  function newArrayNoCopy(objects:Array):RubyArray{
        return RubyArray.newArrayNoCopy(this, objects);
    }
    
  	public  function newBoolean(value:Boolean):RubyBoolean{
        return RubyBoolean.newBoolean(this, value);
    }

 	public  function newEmptyArray():RubyArray{
        return RubyArray.newEmptyArray(this);
    }
    
 	public  function newSymbol(name:String):RubySymbol{
        return symbolTable.getSymbol(name);
    }    

    public  function newLocalJumpError(reason:String, exitValue:IRubyObject, message:String):RaiseException{
        return RaiseException.newInstance(
         	RubyLocalJumpError.newInstance(this,fastGetClass("LocalJumpError"), message, reason, exitValue), true);
    }
    
    public function callEventHooks(context: ThreadContext,ruby_enent_key:int,file:String,line:int,frameName:String,frameKlazz:RubyModule):void{
    	
    } 
  	public  function hasEventHooks():Boolean{
        return _hasEventHooks;
    }       
    public function incGlobalState():void{
    	
    }     
    public function newSecurityError(msg:String):Error{
    	return new Error(msg); 
    }
    public function getStackTraces():int{
    	return this.stackTraces;
    }
    public static function getCurrentInstance():Ruby{
    	return new Ruby();
    }
     public  function setStackTraces(stackTraces:int):void{
        this.stackTraces = stackTraces;
    }
	public function getObjectSpace():ObjectSpace {
        return objectSpace;
    }
    
  	public  function newIndexError(message:String):RaiseException{
        return newRaiseException(fastGetClass("IndexError"), message);
    }
    private  function newRaiseException(exceptionClass:RubyClass, message:String):RaiseException{
        var re: RaiseException =  new RaiseException(this, exceptionClass, message, true);
        return re;
    }
	public function secure(level:int):void {
		
	}
    public function allocModuleId():int{
    	 return moduleLastId.incrementAndGet();
    }
}
}